# -*- coding: utf-8 -*-
import json,time,sqlite3
from datetime import datetime,timedelta
import threading
from threading import Thread
from pysnmp.entity.rfc3413.oneliner import cmdgen
from pysnmp.proto import rfc1902

from Queue import Queue
#具体的处理函数，负责处理单个任务
def do_somthing_using(arguments):
    print 'starting:',arguments['ndip']
    conn=sqlite3.connect(r'ndflow.db3')
    conn.row_factory = sqlite3.Row
    rcv,snt,cpe=get_flow(arguments['ndip'],arguments['iport'])
    if rcv and snt:
        log=datetime.now()
        # print 'rcv:',rcv,'snt:',snt,'log:',log,'cpe:',cpe
        rcv2,snt2,log2=find_prev(arguments['id'],conn)
        # print rcv2,snt2,log2
        if log2:
            try:
                log2=datetime.strptime(log2,'%Y-%m-%d %H:%M:%S.%f')
            except:
                log2=datetime.strptime(log2,'%Y-%m-%d %H:%M:%S')
            deltalog=timedelta.total_seconds(log-log2)
            if deltalog>0:
                rx=(int(rcv)-int(rcv2))*8/deltalog
                tx=(int(snt)-int(snt2))*8/deltalog
                # print 'rx:',rx,'tx:',tx
                if rx<0:
                    rx=tx=0
        else:
            rx=tx=0
            
        add_log((arguments['id'],log,rcv,snt,rx,tx,cpe),conn)
    
    
    
    conn.commit()
    conn.close()
    
#这个是工作进程，负责不断从队列取数据并处理
def working():
    while True:
        arguments = q.get()
        try:
            do_somthing_using(arguments)
        except:
            pass
        q.task_done()
def ndflow_pool(nds):
    s=time.time()
    #把JOBS排入队列
    for i in nds:
        q.put(i)
    #等待所有JOBS完成
    q.join()
    print time.time()-s
q = Queue()
#fork NUM个线程等待队列
NUM = 10
for i in range(NUM):
    t = Thread(target=working)
    t.setDaemon(True)
    t.start()

def get_nds():
    conn=sqlite3.connect(r'ndflow.db3')
    conn.row_factory = sqlite3.Row
    now=datetime.strftime(datetime.now(),'%Y-%m-%d %H:%M:%S.%f')
    nds=conn.execute("select id,ndip,iport from ndflow where dtstart<=? and ?<=dtend",(now,now)).fetchall()
    conn.close()
    return nds
    
def getsnmp(ndip,oid):
    try:
        errorIndication, errorStatus, errorIndex, varBinds = cmdgen.CommandGenerator().getCmd(cmdgen.CommunityData(ndip, 'public'),cmdgen.UdpTransportTarget((ndip, 161)),oid,)
        if errorIndication:
            print errorIndication
            return None
        else:
            if errorStatus:
                print '%s at %s\n' % (
                    errorStatus.prettyPrint(),
                    errorIndex and varBinds[int(errorIndex)-1] or '?'
                    )
                return None
            else:
                for name, val in varBinds:
                    # print '%s:%s = %s' % (ndip,name.prettyPrint(), val.prettyPrint())
                    # snmp=val.prettyPrint()
                    return val.prettyPrint()
    except:
        return None
    
def get_flow(ndip,iport):
    roid=[1,3,6,1,4,1,5959,1,1,2,1,1,3,1]
    roid.append(iport)
    roid=tuple(roid)
    soid=[1,3,6,1,4,1,5959,1,1,2,1,1,8,1]
    soid.append(iport)
    soid=tuple(soid)
    coid=[1,3,6,1,4,1,5959,1,3,1,1,1,2,1]
    # coid.append(iport)
    coid=tuple(coid)
    rcv=getsnmp(ndip,roid)
    snt=getsnmp(ndip,soid)
    cpe=getsnmp(ndip,coid)
    return rcv,snt,cpe
    
def find_prev(id,conn):
    prev=conn.execute('select ircv,isnt,dtlog from ndflowlog where ndflowid=? order by id desc limit 1',(id,)).fetchone()
    if prev:
        return prev
    else:
        return None,None,None
def add_log(flow,conn):
    conn.execute('insert into ndflowlog(ndflowid,dtlog,ircv,isnt,frx,ftx,icpe) values(?,?,?,?,?,?,?)',flow)
    
while True:
    try:
        config = json.load(open("config.txt",'r'))
        delaytime=config["NDFlow"]
        starttime=time.time()
        nds=get_nds()
        ndflow_pool(nds)
        print "threading:",threading.activeCount()
        # write_sqlte3(nds,notalive)

        endtime=time.time()
        sleeptime=delaytime-(endtime-starttime)
        print "sleep ndflow",sleeptime
        if sleeptime>0:
            time.sleep(sleeptime)
    except:
        pass
